export function typeOf(obj) {
  const toString = Object.prototype.toString;
  const map = {
    "[object Boolean]": "boolean",
    "[object Number]": "number",
    "[object String]": "string",
    "[object Function]": "function",
    "[object Array]": "array",
    "[object Date]": "date",
    "[object RegExp]": "regExp",
    "[object Undefined]": "undefined",
    "[object Null]": "null",
    "[object Object]": "object",
  };

  return map[toString.call(obj)];
}

// 扁平化数组
export function flatten(arr) {
  return arr.reduce((prev, item) => {
    return prev.concat(Array.isArray(item) ? flatten(item) : item);
  }, []);
}

export function deepCopy(json) {
  return JSON.parse(JSON.stringify(json));
}

// JSON 转 URL参数
export function parseParams(json) {
  try {
    const tempArr = [];

    for (const i in json) {
      const key = encodeURIComponent(i);

      const value = encodeURIComponent(json[i]);

      tempArr.push(key + "=" + value);
    }
    const urlParamsStr = tempArr.join("&");

    return urlParamsStr;
  } catch (err) {
    return "";
  }
}

const toString = (obj) => JSON.stringify(obj);

export function isEqual(a, b, excludeProps) {
  const aType = typeOf(a);
  const bType = typeOf(b);

  if (aType !== bType) {
    return false;
  }

  let _isEqual = true;

  if (aType === "object") {
    Object.entries(a).forEach(([key, value]) => {
      // 排斥需要鉴定的props
      if (excludeProps && excludeProps.includes(key)) {
        return;
      }
      if (
        b[key].length !== value.length ||
        (!Array.isArray(value) && b[key] !== value)
      ) {
        _isEqual = false;
      }
    });
  }
  if (aType === "array") {
    const _a = a;

    const _b = b;

    if (excludeProps && b.length) {
      const _a = [];

      const _b = [];

      a.forEach((v) => {
        if (typeOf(v) === "object") {
          const item = {
            ...v,
          };

          excludeProps.forEach((prop) => delete item[prop]);
          _a.push(item);
        }
      });
      b.forEach((v) => {
        if (typeOf(v) === "object") {
          const item = {
            ...v,
          };

          excludeProps.forEach((prop) => delete item[prop]);
          _b.push(item);
        }
      });
    }
    if (toString(_a) !== toString(_b)) {
      _isEqual = false;
    }
  }
  return _isEqual;
}

export const Debounce = (fn, delay = 300) => {
  let timer;

  return function () {
    const self = this;

    const args = arguments;

    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(function () {
      timer = null;
      fn.apply(self, args);
    }, delay);
  };
};

export function toChinesNum(num) {
  const changeNum = [
    "零",
    "一",
    "二",
    "三",
    "四",
    "五",
    "六",
    "七",
    "八",
    "九",
  ];

  const unit = ["", "十", "百", "千", "万"];

  const formatedNum = parseInt(num);
  const getWan = (temp) => {
    const strArr = temp.toString().split("").reverse();

    let newNum = "";

    for (let i = 0; i < strArr.length; i++) {
      newNum =
        (i === 0 && strArr[i] === 0
          ? ""
          : i > 0 && strArr[i] === 0 && strArr[i - 1] === 0
          ? ""
          : changeNum[strArr[i]] +
            (Number(strArr[i]) === 0 ? unit[0] : unit[i])) + newNum;
    }
    return newNum;
  };

  const overWan = Math.floor(formatedNum / 10000);

  let noWan = formatedNum % 10000;

  if (noWan.toString().length < 4) {
    noWan = "0" + noWan;
  }
  return overWan ? getWan(overWan) + "万" + getWan(noWan) : getWan(formatedNum);
}

export const guid = () => {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  // querySelector method uses CSS3 selectors for querying the DOM and CSS3
  // doesn't support ID selectors that start with a digit
  // for more:
  // https://stackoverflow.com/questions/37270787/uncaught-syntaxerror-failed-to-execute-queryselector-on-document
  return `cms-${s4()}${s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`;
};

export const arrToMap = (arr, key, valueKey) => {
  const result = Object.create(null);

  if (arr && arr.length) {
    valueKey
      ? arr.forEach((v) => (result[v[key]] = v[valueKey]))
      : arr.forEach((v) => (result[v[key] || v] = v));
  }
  return result;
};

function getSingle(fn) {
  let ret;

  return function () {
    return ret || (ret = fn.apply(this, arguments));
  };
}
const getDiv = getSingle(() => document.createElement("div"));

export const htmlToText = (html) => {
  let text;

  if (document) {
    const div = getDiv();

    div.innerHTML = html;
    text = div.innerText;
  }
  return text || html;
};

// 处理精度丢失的问题
export const dealPrecisionLoss = (num, fixed = 10) => {
  return parseFloat(num).toFixed(fixed);
};

// 权限code
export const powerCodes = {
  key: "powerCodes",
  getPowerCodes() {
    return localStorage.getItem(this.key)?.split(",");
  },
  setPowerCodes(powerCodesArr) {
    localStorage.setItem(this.key, powerCodesArr.join(","));
  },
};

export const getUrlAllQuery = function (url) {
  if (!url && typeof window !== "undefined") {
    url = window.location.href;
  }

  const queryObj = {};
  const reg = /[?&]([^=&#]+)=([^&#]*)/g;
  const query = url.match(reg);

  if (query) {
    // eslint-disable-next-line
    for (const i in query) {
      const params = query[i].split("=");
      const key = params[0].substr(1);
      const value = params[1];

      if (value === "null" || value === "undefined") {
        continue;
      }

      // 需要判断当前内容是否相等，相等情况，覆盖内容
      if (queryObj[key] && queryObj[key] !== value) {
        // 这里需要过滤掉重复内容
        if (!Array.isArray(queryObj[key])) {
          // 添加到数组中
          queryObj[key] = [].concat(queryObj[key], value);
        } else if (queryObj[key].indexOf(value) === -1) {
          // 过滤掉重复的
          queryObj[key] = queryObj[key].concat(value);
        }
      } else {
        queryObj[key] = value;
      }
    }
  }

  return queryObj;
};

export const splitPhone = (phone) => {
  return phone.replace(/\B(?=(?:\d{4})+$)/g, "-");
};

export const useCookie = () => {
  const getCookie = (record) => {
    const cookies = document.cookie.split(";");
    const cookieMap = {};

    cookies.forEach((item) => {
      const [key, value] = item.split("=");
      cookieMap[key.trim()] = value;
    });

    return cookieMap[record];
  };

  return [getCookie];
};

/** 生成唯一id
 * @param Number length > 3
 */
export const genID = (length = 5) => {
  return Number(
    Math.random().toString().substring(3, length) + Date.now()
  ).toString(36);
};
